<!-- 
  Defers initialization of a component until it comes into view.
  Also allows for external loading of the component's module.

  component: a constructor for the component to initialize lazily.
  componentData: The data to pass to the component when initializing.

  This requires us to know the size of the component before it's initialized.
  If nothing is provided, we assign the parent width: 100%; and height: 100%; 
  so you can control its size with a wrapper container with position: relative;

  If you want to control the size directly, you can do so with two properties:

  height: Simply uses this constant value. If a number is given, assumed to be
  pixel height. If a string is given, a css value is assumed and pased directly
  to a css height: "..." declaration. Thus you can use "10vh" as a value.

  aspectRatio (w/h): used the width of the element to compute the height based on 
  this ratio. When aspectRatio is used, an optional property "minHeight" is 
  available and any height values given are ignored.
 -->

<svelte:window on:resize="measure()" />

<div ref:container style="width: {finalWidth}; height: {finalHeight};">
  <Radar bind:ready="radarReady" :offscreen :onscreen height="100%">
    {#if finalReady}
      <svelte:component ref:component this={component} {clientWidth} {clientHeight} {...componentData} />
    {:else}
      <Loading />
    {/if}
  </Radar>
</div>

<script>
  export default {
    components: {
      Radar: "./Radar.html",
      Loading: "./Loading.html"
    },
    data() {
      return {
        component: null,
        url: null,
        componentData: null,
        radarReady: false,
        onscreen: false,
        offsreen: true,
        height: null,
        width: null,
        aspectRatio: null,
        minHeight: null,
        clientWidth: 500,
        clientHeight: 500
      }
    },
    computed: {
      finalReady: ({radarReady, component, clientWidth}) => (clientWidth && radarReady && component) ? true : false,
      finalWidth: ({width}) => {
        if (width) {
          if (typeof width == "number") { return width + "px" }
          if (typeof width == "string") { return width }
        } else {
          return "100%"
        }
      },
      finalHeight: ({clientWidth, height, aspectRatio, minHeight}) => {
        if (aspectRatio) {
          let h = clientWidth / aspectRatio;
          if (minHeight) {
            return Math.min(minHeight, h) + "px";
          } else {
            return h + "px";
          }
        } else if (height) {
          if (typeof height == "number") { return height + "px" };
          if (typeof height == "string") { return height };
        } else {
          return "100%";
        }
      }  
    },
    oncreate() {
      // TODO: Make sure we have some sizes set.
      const {height, aspectRatio} = this.get();
      if (!height && !aspectRatio) {
        console.warn(`Require 'height'${height} or 'aspectRatio'${aspectRatio} not set on LazyComponent.html`, this)
      }
      setTimeout(() => this.measure(), 10);
      // this.measure();
      
    },
    methods: {
      measure() {
        this.set({
          clientWidth: this.refs.container.offsetWidth,
          clientHeight: this.refs.container.offsetHeight,
        })
      },
      getComponent() {
        return this.refs.component;
      }
    },

  }
</script>

<style>
ref:container {
  box-sizing: border-box;
  display: block;
  position: relative;
  overflow: hidden;
  contain: content;
}
</style>